﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.IO;
using KGE.Define;

namespace KGE.Tools
{
    public partial class KMovieMaker : Form
    {
        KMovie kmovie;
        KImagePackage kiset = null;
        Rectangle srcRect;
        string kiset_name;
        bool isKISET = false;
        bool isNPK = false;
        //Size movSize;
        Point mousePoint;
        double playspeed = 1.0;
        Image gif;
        NPK npk;

        //List<KImagePackage> kiss = new List<KImagePackage>();
        //List<KMovie> kms = new List<KMovie>();
        
        FrameDimension fd;

        void select_all()
        {
            try
            {
                srcRect.Location = new Point();
                srcRect.Size = pictureBox1.Image.Size;

                pictureBox1.Invalidate();
            }
            catch { }
        }
        void ins_frm(Image img, int fi,Rectangle srect, Point offset, Size s)
        {
            //if (isKISET == false)
            {
                //KMovieInfo.Frame kif = new KMovieInfo.Frame();
                //kif.KeepSeconds = double.Parse(ui_frametime.Text);
                //kif.DrawLocation = offset;
                //kif.DrawSize = s;
                //kif.KImageIndex = fi;
                //if (ui_se.Text != string.Empty)
                //{
                //    kif.KSoundFileName = ui_se.Text;
                //}
                //kmovieinfo.Frames.Add(kif);

                ///
                KMovie.Frame kf = new KMovie.Frame();
                kf.Length = double.Parse(ui_frametime.Text);
                kf.DrawRectangle.Location = offset;
                kf.DrawRectangle.Size = s;

                Bitmap bm = new Bitmap(kf.DrawRectangle.Size.Width, kf.DrawRectangle.Size.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Graphics g = Graphics.FromImage(bm);
                g.DrawImage(img, new Rectangle(new Point(), kf.DrawRectangle.Size), srect, GraphicsUnit.Pixel);
                kf.KImage = new KImage(img, folder_name + "-" + file_name + "-" + fi.ToString("d3"));

                if (ui_se.Text != string.Empty)
                {
                    kf.KSound = new KSound(ui_se.Text);
                }

                kmovie.Frames.Add(kf);
            }


            trackBar1.Maximum = kmovie.Frames.Count - 1;
        }
        void show_frame_info(int i)
        {
            try
            {
                KMovie.Frame kf = kmovie.Frames[i];
                ui_drawx.Text = "" + kf.DrawRectangle.X;
                ui_drawy.Text = "" + kf.DrawRectangle.Y;
                ui_draww.Text = "" + kf.DrawRectangle.Width;
                ui_drawh.Text = "" + kf.DrawRectangle.Height;
                ui_frametime.Text = "" + kf.Length;

            }
            catch { }
        }
        void play()
        {
            if (trackBar1.Value == kmovie.Frames.Count - 1)
            {
                trackBar1.Value = 0;
            }

            playspeed = double.Parse(ui_spd.Text);

            int i = trackBar1.Value;
            if (kmovie.Frames.Count > 0)
            {
                timer1.Interval = (int)(kmovie.Frames[i].Length * 1000 * playspeed);
                timer1.Enabled = true;
                pictureBox2.Refresh();
            }
        }
        //List<KMovie> KMI2KM(KMovieInfo kmi,List<KImageSet> skis)
        //{
        //    kms.Clear();
        //    foreach (KImageSet k in skis)
        //    {

        //        KMovie km = new KMovie();

        //        km.Size = kmi.Size;

        //        foreach (KMovieInfo.Frame kmif in kmi.Frames)
        //        {
        //            KMovie.Frame kmf = new KMovie.Frame();
        //            kmf.DrawLocation = kmif.DrawLocation;
        //            kmf.DrawSize = kmif.DrawSize;
        //            kmf.FilterColor = kmif.FilterColor;
        //            kmf.KeepSeconds = kmif.KeepSeconds;
        //            kmf.KSound = new KSound(kmif.KSoundFileName);

        //            kmf.KImage = new KImage(k[kmif.KImageIndex]);

        //            km.Frames.Add(kmf);
        //        }
        //        kms.Add(km);
        //    }
        //    return kms;
        //}
        Image get_frm(int i)
        {
            if (isKISET)
            {
                return Image.FromStream(kiset[i].DataStream);

            }
            else if (isNPK)
            {
                return npk[comboBox1.SelectedIndex, i];
            }
            else
            {
                gif.SelectActiveFrame(fd, i);
                return new Bitmap(gif);
            }
        }

        public KMovieMaker()
        {
            InitializeComponent();
            kmovie = new KMovie();
            //kmovieinfo = new KMovieInfo();
        }

        private void gui_load_img_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "*.NPK|*.NPK|Kevin Image Package|*.KIP|*.GIF|*.GIF|*.PNG|*.PNG";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                if (ofd.FileName != string.Empty)
                {
                    isNPK = false;
                    comboBox1.Enabled = false;
                    isKISET = false;
                    if (ofd.FilterIndex == 1)
                    {
                        isNPK = true;
                        comboBox1.Enabled = true;
                        npk = new NPK(System.IO.File.ReadAllBytes(ofd.FileName));
                        comboBox1.Items.Clear();
                        foreach (string str in npk.PackageNames)
                        {
                            comboBox1.Items.Add(str);
                        }
                        pictureBox1.Width = 640;
                        pictureBox1.Height = 480;
                    }
                    else if (ofd.FilterIndex == 2)
                    {
                        load_kis(ofd.FileName);
                    }
                    else if (ofd.FilterIndex == 3)
                    {
                        load_gif(ofd.FileName);
                    }
                    else if (ofd.FilterIndex == 4)
                    {
                    } 
                    
                }
            }


        }
        void load_gif(string fn)
        {
            kiset_name = fn;
            kiset_name = kiset_name.Substring(0, kiset_name.Length - 4);

            gif = Image.FromFile(fn);
            pictureBox1.Image = gif;

            fd = new FrameDimension(gif.FrameDimensionsList[0]);
            int c = gif.GetFrameCount(fd);
            trackBar2.Maximum = c - 1;
            label10.Text = (trackBar2.Value + 1) + " / " + (trackBar2.Maximum + 1);

            //kmovie.Size = pictureBox1.Image.Size;

            pictureBox1.Location = new Point(10, 10);
            pictureBox1.Size = new Size(pictureBox1.Image.Size.Width + 1, pictureBox1.Image.Size.Height + 1);

            select_all();
        }

        void load_kis(string fn)
        {
            folder_name = new FileIndexer(fn).FolderName;
            file_name = new FileIndexer(fn).Name;

            kiset = (KImagePackage)Util.LoadObject(fn);

            pictureBox1.Image = Image.FromStream(kiset[0].DataStream);

            trackBar2.Maximum = kiset.Count - 1;

            isKISET = true;

            ui_kmisname.Text = new FileIndexer(fn).Name;

            int c = kiset.Count;
            trackBar2.Maximum = c - 1;
            label10.Text = (trackBar2.Value + 1) + " / " + (trackBar2.Maximum + 1);

            //kmovie.Size =  pictureBox1.Image.Size;

            pictureBox1.Location = new Point(10, 10);
            pictureBox1.Size = new Size(pictureBox1.Image.Size.Width + 1, pictureBox1.Image.Size.Height + 1);

            select_all();
        }

        string folder_name;
        string file_name;

        private void ui_loadse_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "*.mp3|*.mp3";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                if (ofd.FileName != string.Empty)
                {
                    ui_se.Text = ofd.FileName;
                }
            }
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            srcRect.Location = e.Location;

       }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            mousePoint = e.Location;

            //mousePoint.X--;
            //mousePoint.Y--;

            if (e.Button == MouseButtons.Left)
            {
                srcRect.Width = e.X - srcRect.X;
                srcRect.Height = e.Y - srcRect.Y;

                //srcRect.Width--;
                //srcRect.Height--;

                pictureBox1.Invalidate();
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                srcRect.Width = e.X - srcRect.X;
                srcRect.Height = e.Y - srcRect.Y;

                //srcRect.Width--;
                //srcRect.Height--;
            }
            else if (e.Button == MouseButtons.Right)
            {
                select_all();
            }

            pictureBox1.Invalidate();
        }
        
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (pictureBox1.Image == null)
            {
                return;
            }

            Graphics g = e.Graphics;
            g.Clear(Color.CornflowerBlue);
            Point p = new Point(1, 1);
            if (isNPK)
            {
                p = npk.GetImageLocation(comboBox1.SelectedIndex, trackBar2.Value); 
            }
            g.DrawImage(pictureBox1.Image, p.X, p.Y, pictureBox1.Image.Width, pictureBox1.Image.Height);
            //Point p = new Point(srcRect.Right, srcRect.Bottom);
            //g.DrawString("" + mousePoint, new Font("黑体", 16, FontStyle.Bold, GraphicsUnit.Pixel), Brushes.Red, mousePoint);
            Rectangle r = srcRect;
            //r.Width++;
            //r.Height++;
            g.DrawRectangle(new Pen(Color.Red), r);

        }
        
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            if (trackBar1.Value == kmovie.Frames.Count)
            {
                trackBar1.Value = 0;
            }
            show_frame_info(trackBar1.Value);
            pictureBox2.Refresh();
        }

        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            if (isKISET)
            {
                label10.Text = (trackBar2.Value + 1) + " / " + (trackBar2.Maximum + 1);
                pictureBox1.Image = Image.FromStream(kiset[trackBar2.Value].DataStream);
            }
            else if (isNPK)
            {
                label10.Text = (trackBar2.Value) + " / " + (trackBar2.Maximum);
                pictureBox1.Image = npk[comboBox1.SelectedIndex, trackBar2.Value];
                ui_drawx.Text = "" + npk.GetImageLocation(comboBox1.SelectedIndex, trackBar2.Value).X;
                ui_drawy.Text = "" + npk.GetImageLocation(comboBox1.SelectedIndex, trackBar2.Value).Y;
                ui_draww.Text = "" + pictureBox1.Image.Width;
                ui_drawh.Text = "" + pictureBox1.Image.Height;
            }
            else
            {
                label10.Text = (trackBar2.Value + 1) + " / " + (trackBar2.Maximum + 1);
                pictureBox1.Image = get_frm(trackBar2.Value);
            }
        }

        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            if (kmovie.Frames.Count == 0)
            {
                return;
            }
            Graphics g = e.Graphics;
            g.Clear(Color.CornflowerBlue);
            int i = trackBar1.Value;

            //if (kms.Count > 0)
            //{
            //    Point ppp = new Point(10, 10);
            //    foreach (KMovie kmn in kms)
            //    {
            //        g.DrawImage(kmn.Frames[i].KImage.Image, ppp);
            //    }
            //}
            //else
            {
                if (i < kmovie.Frames.Count)
                {
                    //int w = kmovie.Size.Width;
                    //int h = kmovie.Size.Height;

                    //Point p = new Point(10, 10 + h);
                    Point p = kmovie.Frames[i].DrawRectangle.Location;

                    //p.Y -= h;
                    //g.DrawRectangle(new Pen(Color.Red), new Rectangle(p, kmovie.Size));
                    //p.X -= kmovie.Frames[i].KImage.Size.Width / 2;

                    g.DrawImage(Image.FromStream(kmovie.Frames[i].KImage.DataStream), p);


                    Point pp = new Point();
                    g.DrawLine(Pens.Red, new Point(pp.X - 5, pp.Y), new Point(pp.X + 5, pp.Y));
                    g.DrawLine(Pens.Red, new Point(pp.X, pp.Y - 5), new Point(pp.X, pp.Y + 5));

                    g.DrawString(pp.ToString(), new Font("微软雅黑", 12), Brushes.Red, pp);
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;

            int i = trackBar1.Value;
            try
            {
                trackBar1.Value++;
                pictureBox2.Refresh();
                timer1.Interval = (int)(kmovie.Frames[trackBar1.Value].Length * 1000 * playspeed);
                timer1.Enabled = true;
            }
            catch
            {
                if (ui_loop.Checked)
                {
                    play();
                }
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            ui_fx.Text = "" + srcRect.X;
            ui_fy.Text = "" + srcRect.Y;
            ui_draww.Text = ui_w.Text = "" + srcRect.Width;
            ui_drawh.Text = ui_h.Text = "" + srcRect.Height;
            label7.Text = "" + mousePoint;


            //ui_movw.Text = "" + kmovie.Size.Width;
            //ui_movh.Text = "" + kmovie.Size.Height;

            if (kmovie.Frames.Count == 0)
            {
                label12.Text = (trackBar1.Value ) + " / " + (kmovie.Frames.Count);
            }
            else
            {
                label12.Text = (trackBar1.Value + 1) + " / " + (kmovie.Frames.Count);
            }
        }

        private void ui_stop_Click(object sender, EventArgs e)
        {
            trackBar1.Value = 0;
            pictureBox2.Refresh();
            timer1.Enabled = false;
        }

        private void ui_play_Click(object sender, EventArgs e)
        {
            play();
        }

        private void ui_output_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "*.KMovie|*.KM";
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                if (sfd.FileName != string.Empty)
                {
                    kmovie.Name = file_name;
                    Util.SaveObject(sfd.FileName, kmovie);
                    MessageBox.Show("输出成功");
                }
            }
        }

        private void ui_load_kmovie_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "*.KMovie|*.KM";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                if (ofd.FileName != string.Empty)
                {
                    kmovie = (KMovie)Util.LoadObject(ofd.FileName);
                    trackBar1.Maximum = kmovie.Frames.Count - 1;
                }
            }
        }

        private void ui_pref_Click(object sender, EventArgs e)
        {
            try
            {
                trackBar1.Value--;
            }
            catch {
                trackBar1.Value = kmovie.Frames.Count;
            }
            pictureBox2.Refresh();
        }

        private void ui_nxtf_Click(object sender, EventArgs e)
        {
            trackBar1.Value++;
            if (trackBar1.Value == kmovie.Frames.Count)
            {
                trackBar1.Value = 0;
            }
            pictureBox2.Refresh();
        }

        private void ui_mod_Click(object sender, EventArgs e)
        {
            int i = trackBar1.Value;
            KMovie.Frame kf = kmovie.Frames[i];
            kf.Length = double.Parse(ui_frametime.Text);
            kf.DrawRectangle.Size = new Size(int.Parse(ui_draww.Text), int.Parse(ui_drawh.Text));
            kf.DrawRectangle.Location = new Point(int.Parse(ui_drawx.Text), int.Parse(ui_drawy.Text));

            //KMovieInfo.Frame kif = kmovieinfo.Frames[i];
            //kif.KeepSeconds = double.Parse(ui_frametime.Text);
            //kif.DrawSize = new Size(int.Parse(ui_draww.Text), int.Parse(ui_drawh.Text));
            //kif.DrawLocation = new Point(int.Parse(ui_drawx.Text), int.Parse(ui_drawy.Text));

        }

        private void ui_modall_Click(object sender, EventArgs e)
        {
            double t = double.Parse(ui_frametime.Text);
            for (int i = 0; i < kmovie.Frames.Count; i++)
            {
                kmovie.Frames[i].Length = t;
            }
            //for (int i = 0; i < kmovieinfo.Frames.Count; i++)
            //{
            //    kmovieinfo.Frames[i].KeepSeconds = t;
            //}
        }

        private void ui_ins_img_Click(object sender, EventArgs e)
        {
            srcRect.X = int.Parse(ui_fx.Text);
            srcRect.Y = int.Parse(ui_fy.Text);
            srcRect.Width = int.Parse(ui_w.Text);
            srcRect.Height = int.Parse(ui_h.Text);

            pictureBox1.Refresh();
        }

        private void ui_qins_Click(object sender, EventArgs e)
        {
            int ff = int.Parse(ui_insf.Text);
            int ft = int.Parse(ui_inst.Text);
            ff--;
            ft--;
            if (ff >= ft)
            {
                Size img_size = pictureBox1.Image.Size;

                if (img_size.Width % srcRect.Width == 0 && img_size.Height % srcRect.Height == 0)
                {
                    int wc = img_size.Width / srcRect.Width;
                    int hc = img_size.Height / srcRect.Height;

                    for (int y = 0; y < hc; y++)
                    {
                        for (int x = 0; x < wc; x++)
                        {
                            Rectangle r = new Rectangle();
                            r.X = x * srcRect.Width;
                            r.Y = y * srcRect.Height;
                            r.Size = srcRect.Size;
                            ins_frm(pictureBox1.Image, trackBar1.Value, r, new Point(), r.Size);
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i <= ft - ff; i++)
                {
                    if (isNPK)
                    {
                        Image img = npk[comboBox1.SelectedIndex, ff + i];
                        Rectangle rect = new Rectangle();
                        rect.Size = img.Size;
                        Point o = npk.GetImageLocation(comboBox1.SelectedIndex, ff + i);
                        Size s = img.Size;
                        ins_frm(img, i + ff, rect, o, s);
                    }
                    else
                    {
                        pictureBox1.Image = get_frm(i + ff);
                        Point o = new Point(int.Parse(ui_drawx.Text), int.Parse(ui_drawy.Text));
                        Size s = new Size(int.Parse(ui_draww.Text), int.Parse(ui_drawh.Text));
                        ins_frm(pictureBox1.Image, i + ff, srcRect, o, s);
                    }
                }
            }
        }

        private void ui_ins_Click(object sender, EventArgs e)
        {
            Point o = new Point(int.Parse(ui_drawx.Text), int.Parse(ui_drawy.Text));
            Size s = new Size(int.Parse(ui_draww.Text), int.Parse(ui_drawh.Text));
            ins_frm(pictureBox1.Image, trackBar1.Value, srcRect, o, s);
        }

        private void ui_del_Click(object sender, EventArgs e)
        {
            try
            {
                int i = trackBar1.Value;
                kmovie.Frames.RemoveAt(i);
                //kmovieinfo.Frames.RemoveAt(i);
                trackBar1.Maximum = kmovie.Frames.Count - 1;
                pictureBox2.Refresh();
            }
            catch { }
        }

        private void ui_clr_Click(object sender, EventArgs e)
        {
            if (DialogResult.Yes == MessageBox.Show("确定要清除所有帧？",    //Message Text
                                "注意",                        //MBox Title
                                MessageBoxButtons.YesNo,       //Buttons to show
                                MessageBoxIcon.Question,       //Icon shown
                                MessageBoxDefaultButton.Button2)) //Default button
            {
                //kmovie.Frames.Clear();
                kmovie = new KMovie();
                //kmovie.Size = pictureBox1.Image.Size;
                //kmovieinfo = new KMovieInfo();
                //kmovieinfo.Size = pictureBox1.Image.Size;
                trackBar1.Value = trackBar1.Maximum = 0;
                pictureBox2.Refresh();
            }
        }

        private void ui_makesuresize_Click(object sender, EventArgs e)
        {
            try
            {
                Size movSize = new System.Drawing.Size(int.Parse(ui_movw.Text), int.Parse(ui_movh.Text));
                //kmovie.Size = movSize;
                pictureBox2.Refresh();
            }
            catch { }
        }

        private void ui_output_kiset_Click(object sender, EventArgs e)
        {
            //kiset = new KImageSet(gif);

            Util.SaveObject(kiset_name + ".KIS", kiset);
        }

        private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                //kmovie.Location = e.Location;
                pictureBox2.Refresh();
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            trackBar2.Maximum = npk.GetImageCount(comboBox1.SelectedIndex) - 1;
        }

    }
}
